﻿using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Linq.Expressions;
using System.Transactions;
using Amazon.DynamoDBv2.Model;
using AmazonDynamoDBStub.Models;
using AmazonDynamoDBStub.Repositories;

namespace AmazonDynamoDBStub.EntityFramework
{
    public class DynamoDBAttributeRepository : RepositoryBase<DynamoDBAttribute>, IDynamoDBAttributeRepository
    {
        public DynamoDBAttributeRepository(DbContext context)
            : base(context)
        {
        }

        public IGrouping<Guid, DynamoDBAttribute> CreateItem(string tableName, params KeyValuePair<string, AttributeValue>[] keyAttributes)
        {
            Guid rowId = Guid.NewGuid();
            var attributeList = new List<DynamoDBAttribute>();

            using (TransactionScope ts = new TransactionScope())
            {
                foreach (var keyAttribute in keyAttributes)
                {
                    var attributeToAdd = DynamoDBAttributeFactory.Create(tableName, rowId, keyAttribute);
                    attributeList.Add(attributeToAdd);
                    this.Add(attributeToAdd);
                }

                ts.Complete();
            }

            var item = attributeList.GroupBy(attr => attr.RowId).Single();
            return item;
        }

        public IGrouping<Guid, DynamoDBAttribute> GetItem(string tableName, Expression<Func<IGrouping<Guid, DynamoDBAttribute>, bool>> predicate)
        {
            var attributesFromSpecificTable = this.FindAll(attr => attr.TableName == tableName).AsQueryable().Include("DynamoDBTable");
            var rowsFromSpecificTable = attributesFromSpecificTable.GroupBy(attr => attr.RowId);
            return rowsFromSpecificTable.Where(predicate).SingleOrDefault();
        }

        public IEnumerable<IGrouping<Guid, DynamoDBAttribute>> FindItems(string tableName, Expression<Func<IGrouping<Guid, DynamoDBAttribute>, bool>> predicate)
        {
            var attributesFromSpecificTable = this.FindAll(attr => attr.TableName == tableName).AsQueryable().Include("DynamoDBTable");
            var rowsFromSpecificTable = attributesFromSpecificTable.GroupBy(attr => attr.RowId);
            return rowsFromSpecificTable.Where(predicate).ToList();
        }

        public void RemoveItem(IGrouping<Guid, DynamoDBAttribute> item)
        {
            var attributesToRemove = this.FindAll(attr => attr.RowId == item.Key);

            using (TransactionScope ts = new TransactionScope())
            {
                foreach (var attributeToRemove in attributesToRemove)
                {
                    this.Remove(attributeToRemove);
                }

                ts.Complete();
            }
        }

        public int GetItemCount(string tableName)
        {
            return this.DbSet.Count(t => t.TableName == tableName);
        }

        protected override void Dispose(bool disposing)
        {
            base.Dispose(disposing);
        }
    }
}
